/*******************************************************************************
 * Copyright 2010 Ben Knowles
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.midtro.attolog;

/**
 * The internal logging levels.
 * There are a couple of special levels such as {@link #OFF} and {@link #ON}.
 * 
 * Adapted from the 'DebugLevel' class.
 * 
 * @author Ben Knowles
 */
enum Level {

	/**
	 * Logging messages are not displayed.
	 */
	OFF(0, "off"),
	
	/**
	 * This should be used when an unexpected error occurs that is serious enough
	 * to cause or warrant the halting of the current process or even the whole application. 
	 */
	FATAL(1, "fatal"),
	
	/**
	 * This should be used when an unexpected error occurs that cannot be recovered from. 
	 */
	ERROR(2, "error"),
	
	/**
	 * This should be used when an unexpected error occurs that CAN be recovered from.
	 */
	WARN(3, "warn"),
	
	/**
	 * This should be used for reporting information to the end user.
	 */
	INFO(4, "info"),
	
	/**
	 * This should be used for the most basic debugging statements. 
	 * This may include the direction taken in a control structure, events fired or received
	 * and the state of important objects or variables. 
	 */
	DEBUG(5, "debug"),
	
	/**
	 * This should be used for debugging statements that produce a large amount of output, are called
	 * often, or that don't need to be seen when performing high-level debugging. This could include
	 * extraneous events (e.g. keyboard or mouse events), the state of not-so-important objects or
	 * variables, and statements that exist within a loop. It is recommended that method parameters
	 * and return values be logged at this level (unless the amount of output they produce is "ludicrous"). 
	 */
	VERBOSE(6, "verbose"),
	
	/**
	 * This should be used for debugging statements that produce a ridiculous wealth of
	 * output, e.g. printing a line for every pixel in an image. 
	 */
	LUDICROUS(7, "ludicrous"),
	
	/**
	 * An alias for {@link #LUDICROUS}.
	 */
	ALL(7, "all");
	
	private final int level;
	private final String name;
	
	/**
	 * Creates a new level.
	 * @param level The level filter ID.
	 * @param name The level name.
	 */
	private Level(final int level, final String name){
		this.level = level;
		this.name = name;
	}
	
	/**
	 * Whether or not the message should be logged occording to the current log level.
	 * @param logLevel The log level to compare to.
	 * @return Whether or not we should log it.
	 */
	public boolean shouldLog(Level logLevel){
		return this != OFF && logLevel.level <= this.level;
	}

	/**
	 * Gets the log filter ID.
	 */
	public int getLevel(){
		return level;
	}

	/**
	 * Gets the level name.
	 * We could use the enum for this, but if the code is obfuscated this becomes a problem.
	 */
	public String getName(){
		return name;
	}
	
	/**
	 * Gets a level by name. Ignores case.
	 * @param name The name to find.
	 * @return The level if found, null otherwise.
	 */
	public static Level forName(String name){
		for(Level level : Level.values()){
			if(level.name.equalsIgnoreCase(name)){
				return level;
			}
		}
		
		return null;
	}
	
	/**
	 * Gets a level by filter ID.
	 * @param id The id to find.
	 * @return The level if found, null otherwise.
	 */
	public static Level forID(int id){
		for(Level level : Level.values()){
			if(level.level == id){
				return level;
			}
		}
		
		return null;
	}
}
